package com.lqk.demo.jmm.visibility;

import lombok.extern.slf4j.Slf4j;

import static com.lqk.demo.n2.util.Sleeper.sleep;

/**
 * @author lqk
 * @date 2021/12/26 13:08
 *
 * 使用 synchronized ()，保证变量的可见性
 *
 * 注意 synchronized 语句块既可以保证代码块的原子性，也同时保证代码块内变量的可见性。但缺点是
 * synchronized 是属于重量级操作，性能相对更低
 * 如果在前面示例的死循环中加入 System.out.println() 会发现即使不加 volatile 修饰符，线程 t 也能正确看到
 * 对 run 变量的修改了，想一想为什么？
 *
 * 使用了synchronized ()保证了可见性和原子性
 *  private void newLine() {
 *         try {
 *             synchronized (this) {
 *                 ensureOpen();
 *                 textOut.newLine();
 *                 textOut.flushBuffer();
 *                 charOut.flushBuffer();
 *                 if (autoFlush)
 *                     out.flush();
 *             }
 *         }
 *         catch (InterruptedIOException x) {
 *             Thread.currentThread().interrupt();
 *         }
 *         catch (IOException x) {
 *             trouble = true;
 *         }
 *     }
 *
 */
@Slf4j
public class TestVisibility3 {
    static boolean run = true;
    // 使用 synchronized ()，保证变量的可见性
    // 锁对象
    final static Object lock = new Object();
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (true){
                synchronized (lock){
                    System.out.println();
                    if (!run){
                        break;
                    }
                }
            }
        });
        t.start();
        sleep(1);

        log.debug("停止线程t");
        synchronized (lock){
            run = false;    // 线程停止
        }
    }
}
